package com.gzk.hrm.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.gzk.hrm.constants.UserConstants;
import com.gzk.hrm.domain.Login;
import com.gzk.hrm.domain.VipAccount;
import com.gzk.hrm.domain.VipBase;
import com.gzk.hrm.domain.VipUser;
import com.gzk.hrm.dto.UserRegisterDto;
import com.gzk.hrm.dto.VerifyCodeDto;
import com.gzk.hrm.feign.AuthLoginFeign;
import com.gzk.hrm.mapper.VipUserMapper;
import com.gzk.hrm.service.IVipAccountService;
import com.gzk.hrm.service.IVipBaseService;
import com.gzk.hrm.service.IVipUserService;
import com.gzk.hrm.util.*;
import com.netflix.discovery.converters.Auto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 会员登录账号 服务实现类
 * </p>
 *
 * @author jake.Chen
 * @since 2022-02-18
 */
@Service
@Slf4j
public class VipUserServiceImpl extends ServiceImpl<VipUserMapper, VipUser> implements IVipUserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private AuthLoginFeign authLoginFeign;

    @Autowired
    private IVipBaseService vipBaseService;

    @Autowired
    private IVipAccountService vipAccountService;

    @Override
    public String getImageCode(String imageCodeKey) {
        String code = VerifyCodeUtils.generateVerifyCode(4, VerifyCodeUtils.VERIFY_CODES);
        //存redis
        redisTemplate.opsForValue().set(imageCodeKey,code);
        String base64Code = null;
        try {
            //生成图形验证码
            base64Code = VerifyCodeUtils.VerifyCode(100, 50, code);
            log.info("生成验证码成功");
        } catch (IOException e) {
            e.printStackTrace();
            log.error("生成验证码失败失败");
        }

        return base64Code;
    }

    @Override
    public void sendSmsCode(VerifyCodeDto dto) {

        String imageCodeKey = dto.getImageCodeKey();
        String imageCode = dto.getImageCode();
        String mobile = dto.getMobile();

        //参数验证
        AssertUtils.isNotEmpty(imageCode, "图形验证码为空了！！");
        AssertUtils.isNotEmpty(imageCodeKey, "系统错误，图片验证码业务键为空！");
        AssertUtils.isNotEmpty(mobile, "手机号不能为空！");

        //参数验证完成之后从redis中取出数据
        String redisImgCode = (String) redisTemplate.opsForValue().get(imageCodeKey);

        //防御编程
        AssertUtils.isNotEmpty(redisImgCode, "少年郎，不要搞事情");
        //判断图形验证码是否正确
        AssertUtils.isTrue(redisImgCode.equalsIgnoreCase(imageCode), "图形验证码错误，请重新输入");
        //如果相等就发送手机验证码
        sendSmsVerifyCode(mobile);


    }


    /**
     * 发送手机验证码
     * @param mobile
     */
    private void sendSmsVerifyCode(String mobile) {
        //先根据电话号码从redis中取
        String redisMobileCode = (String) redisTemplate.opsForValue().get(UserConstants.PHONE_REQESTER_VERIFY_CODE_PREFIX + mobile);

        //判断为空吗
        String code = null;
        if(StringUtils.hasLength(redisMobileCode)){
            //有值，判断时间过了一分钟了吗
            Long setTime = Long.valueOf(redisMobileCode.split(":")[1]);
            //用当前时间减去设置时间
            AssertUtils.isTrue((System.currentTimeMillis()-setTime)>60*1000, "少年郎，你还年轻！");
            //大于一分钟小于三分钟,用之前的验证码
            code = redisMobileCode.split(":")[0];
        }else {
            //生成code
            code = StrUtils.getComplexRandomString(4);
        }

        //存redis
        redisTemplate.opsForValue().set(UserConstants.PHONE_REQESTER_VERIFY_CODE_PREFIX + mobile, code+":"+ System.currentTimeMillis(),5, TimeUnit.MINUTES);

        //todo 发送验证手机验证码
        System.out.println("验证码为："+code);

    }

    /**
     * 用户注册
     * @param dto
     */
    @Override
    public void register(@Valid UserRegisterDto dto) {
        String mobile = dto.getMobile();
        String password = dto.getPassword();
        String smsCode = dto.getSmsCode();
        Integer channel = dto.getRegChannel();


        //判断手机号是否被注册
        Wrapper<VipUser> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", mobile);
        VipUser vipUser = selectOne(wrapper);
        //判断
        AssertUtils.isNull(vipUser, "手机号已经被注册！");


        //判断手机验证码是否正确
        //从redis中取值
        String key = UserConstants.PHONE_REQESTER_VERIFY_CODE_PREFIX + mobile;
        String codeFromRedis = (String) redisTemplate.opsForValue().get(key);
        AssertUtils.isNotEmpty(codeFromRedis, "验证码已过期");
        //比较
        AssertUtils.isEqualsIngoreCase(smsCode, codeFromRedis.split(":")[0], "验证码不正确！");

        //调用feign保存login信息
        Login login = new Login();
        login.setType(Login.USER);
        login.setUsername(mobile);
        login.setPassword(password);
        AjaxResult result = authLoginFeign.save(login);
        AssertUtils.isTrue(result.isSuccess(), "服务调用失败");
        AssertUtils.isNotNull(result.getResultObj(), "auth服务瓦了！");

        //保存vipUser的信息
        VipUser user = new VipUser();
        user.setCreateTime(System.currentTimeMillis());
        user.setBitState(BitStatesUtils.OP_ACTIVED+BitStatesUtils.OP_AUTHED_PHONE+BitStatesUtils.OP_REGISTED);
        user.setLoginId(Long.valueOf(result.getResultObj().toString()));
        user.setNickName(mobile);
        user.setPhone(mobile);
        insert(user);

        //保存base信息
        VipBase vipBase = new VipBase();
        vipBase.setCreateTime(System.currentTimeMillis());
        vipBase.setSsoId(user.getId());
        vipBase.setRegTime(System.currentTimeMillis());
        vipBase.setRegChannel(channel);

        vipBaseService.insert(vipBase);


        //保存账户信息
        VipAccount vipAccount = new VipAccount();
        vipAccount.setUserId(user.getId());
        vipAccount.setAmount(new BigDecimal("0"));
        vipAccountService.insert(vipAccount);


        //删除redis中的短信验证码
        redisTemplate.delete(key);

    }
}
